package com.git.hui.yinshua.biz.util;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author YiHui
 * @date 2024/6/13
 */
public class DiffUtil {
    @Data
    public static class DiffRes<T> {
        private List<T> adds;

        private List<T> updates;

        private List deletes;
    }

    /**
     * 数据对比
     *
     * @param dbRecords
     * @param newRecords
     * @param <N>
     * @param <R>
     * @return
     */
    public static <N, R> DiffRes<N> diffRecord(List<R> dbRecords, List<N> newRecords, Function<R, Object> dbKeyFunc, Function<N, Object> newKeyFunc) {
        // db中存在，新的记录中不存在的，表示需要删除
        List toDeletes = new ArrayList<>();
        // 新的有，db中没有
        List<N> toAdds = new ArrayList<>();
        // 同时有
        List<N> toUpdates = new ArrayList<>();

        // 对于没有主键的，直接加入新增列表
        newRecords = newRecords.stream().filter(s -> {
            Object key = newKeyFunc.apply(s);
            if (key == null) {
                toAdds.add(s);
                return false;
            }
            return true;
        }).collect(Collectors.toList());

        Map<Object, R> dbMap = dbRecords.stream().collect(Collectors.toMap(dbKeyFunc::apply, s -> s));
        Map<Object, N> newMap = newRecords.stream().collect(Collectors.toMap(newKeyFunc::apply, s -> s));


        newMap.forEach((key, val) -> {
            if (dbMap.containsKey(key)) {
                // 同时存在，放入更新
                toUpdates.add(val);
            } else {
                // 新的有，db中无，插入
                toAdds.add(val);
            }
        });
        dbMap.keySet().forEach(key -> {
            if (!newMap.containsKey(key)) {
                // db有，新的无
                toDeletes.add(key);
            }
        });
        DiffRes<N> res = new DiffRes<>();
        res.adds = toAdds;
        res.deletes = toDeletes;
        res.updates = toUpdates;
        return res;
    }
}
